# Mybatis 动态SQL
关键字:if where set trim choose when otherwise foreach
if
choose (when, otherwise)
trim (where, set)
foreach
# 1.if
**if
**标签:查询条件是可选项(ps:博客文章搜索)
<select>
select * from blog where 1=1
<if test="title != null">
and title LIKE #{title}
</if>
<if test="author != null">
and type = #{type}
</if>
<if test="recommend != null">
and recommend=#{recommend};
</if>
</select>
2
3
4
5
6
7
8
9
10
11
12
test
为条件,多个条件为and
连接,并非&&
where 1=1 if里面加入and
# 2.where
<select>
select * from blog
<where>
<if test="title != null">
and title LIKE #{title}
</if>
<if test="author != null">
and type = #{type}
</if>
<if test="recommend != null">
and recommend=#{recommend};
</if>
</where>
</select>
2
3
4
5
6
7
8
9
10
11
12
13
14
SQL
语句的where
关键字变成where
标签,包裹住后面的if标签而已。
作用:如果标签中有返回值的话,就插入一个where。
如果标签返回值是以and或者or开头的,这回剔除掉。
例如:如果只有author
不为null
,则前面的and
会自动剔除掉
select * from blog where type=#{type}
# 3.set
类似与where,用于更新语句中。
set用逗号隔开,where用and/or隔开
<update>
update blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="type != null">
type = #{type},
</if>
<if test="recommend != null">
recommend = #{recommend}
</if>
</set>
where id = #{id};
</update>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 4.trim
如果 where
元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where
元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
2
3
prefixOverrides
属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides
属性中指定的内容,并且插入 prefix
属性中指定的内容。
3.3.2 与 set 元素等价的自定义 trim 元素
<trim prefix="SET" suffixOverrides=",">
...
</trim>
2
3
注意,我们覆盖了后缀值设置,并且自定义了前缀值。
# 5.choose
MyBatis
提供了 choose
元素,它有点像 Java
中的 switch
语句。
<select>
select * from blog where
<choose>
<when test="title != null">
title like #{title}
</when>
<when test="type != null">
type = #{type}
</when>
<otherwise>
recommend = 1;
</otherwise>
</choose>
</select>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 6.foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。
动态 `SQL` 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。
2
foreach
元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item
)和索引(index
)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
提示 你可以将任何可迭代对象(如 List、Set
等)、Map
对象或者数组对象作为集合参数传递给 foreach
。当使用可迭代对象或者数组时,index
是当前迭代的序号,item
的值是本次迭代获取到的元素。当使用 Map
对象(或者 Map.Entry
对象的集合)时,index
是键,item
是值。
解决SQL 中 in 中遍历的问题,因为通常会传递一个集合,以往要使用Java来遍历改集合中的元素,然后拼接SQL语句。例如下面的SQL语句:传递一个集合{3,5,9}
-- 查询学号为3,5,9的博客的标题,分类,是否推荐
SELECT title,type,recommend FROM blog where id IN(3,5,9);
-- 等价于
SELECT title,type,recommend FROM blog where id =3 OR id =5 OR id =9;
-- 也等价于:SELECT id,name,major FROM blog where 1=1 and (id=3 or id=5 or id=9);
List<Blog> queryBlogForeach(Map map);
1
SELECT title,type,recommend FROM blog where id IN(3,5,9);
或者其等价SQL:SELECT title,type,recommend FROM blog where id =3 OR id =5 OR id =9;
`(3,5,9)以集合形式保存在map中key为idListforeach要做的就是 遍历idList对应的value获取值
foreah
使用:
collection:
指定输入对象中的集合属性 上述例子为 idList
item
:每次遍历生成的对象取的名称 上述例子中可取名id(自定义取名,后面用#{}获取)
open:
开始遍历时的拼接字符串 上述例子为 左括号 (
close
:结束时拼接的字符串 上述例子为 右括号 )
separator
:遍历对象之间需要拼接的字符串 上述例子为 逗号 ,
<!--SELECT title,type,recommend FROM blog where id IN(3,5,9);-->
<select id="selectBlogForeach" parameterType="map" resultType="com.piao.pojo.Blog">
SELECT title,type,recommend FROM blog
<where>
id in
<foreach collection="idList" item="id" open="(" close=");" separator=",">
#{id}
</foreach>
</where>
</select>
<!-- 若采取它的的等价sql:
SELECT title,type,recommend FROM blog where id =3 OR id =5 OR id =9;
那么foreach写法略有不同
-->
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<select id="selectBlogForeach" parameterType="map" resultType="com.piao.pojo.Blog">
SELECT title,type,recommend FROM blog
<where>
<foreach collection="idList" item="id" open="(" close=");" separator="OR">
id = #{id}
</foreach>
</where>
</select>
2
3
4
5
6
7
8
# 拓展 1 trim元素常用场景 insert语句
一般插入多个数据,但都是可选项,使用自定义trim元素包裹最合适,就是
majorid和majorname
都是可选项`
INSERT INTO `major`(`majorid`,`majorname`) values(9,'大数据科学');
INSERT INTO `major`(`majorid`,) values(9);
INSERT INTO `major`(`majorname`) values('大数据科学');
2
3
4
可用以下insert元素和trim元素
实现:
<insert id="insertBlogByTrim" parameterType="">
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="majorid != null">
majorid,
</if>
<if test="majorname != null">
majorname,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="majorid != null">
#{adminUserId},
</if>
<if test="majorname != null">
#{loginUserName},
</if>
</trim>
</insert>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 拓展2 SQL片段
在Mapper.xml中可用sql元素提取重复使用的sql片段,在需要复用的地方使用include元素引用即可,类似于c/c++头文件的意思。
sql元素使用 id 来唯一标识该sql片段 include元素中使用 refid 来指定引用的sql片段 例如以下代码:
<sql id="Base_Column_List">
category_id, category_name, category_icon, category_rank, is_deleted, create_time
</sql>
<select id="findCategoryList" parameterType="Map" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from tb_blog_category
where is_deleted=0
order by category_rank desc,create_time desc
<if test="start!=null and limit!=null">
limit #{start},#{limit}
</if>
</select>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 拓展3 mybatis+多数据库支持
数据库之间实现某个功能的函数可能方法不一样
同时为了方便数据迁移,mybatis
提供了多数据库支持,在jdbc
中会返回数据库驱动name
。
需要在配置文件中environment
标签里加入 databaseIdProvider
标签来启用这个功能。
<environment>
<databaseIdProvider type="DB_VENDOR" />
</environment>
2
3
配置数据库Id
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
2
3
4
利用databaseId
属性来指定数据库类型,以使用方言。
<select datebaseId="数据库别名(配置文件中的value)">
.....
</select>
2
3